
import threading
from threading import Lock
import subprocess
import select
import queue
import time

"""
pipe.readlines() 会阻塞到程序退出。 
pipe.readline() 会阻塞到程序产生一行输出。 

proc.communicate() 会阻塞到程序退出。 

"""


class PikafishPool:
    """这个类可能有内存泄露的问题。 """
    def __init__(self, engine_path, pool_size=1):
        self.engines = []
        self.output_queue = []
        self.locks = [Lock() for _ in range(pool_size)]
        for i in range(pool_size):
            proc = subprocess.Popen(
                engine_path,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                universal_newlines=True,
                bufsize=1
            )

            # output = proc.stdout.readlines()
            # print(output)
            # output = proc.stdout.readline()
            # print(output)
            # output = self.get_output(proc)
            self.output_queue.append(queue.Queue())
            self.engines.append(proc)
            read_thread = threading.Thread(
                target=self._read_output,
                args=(i,),
                daemon=True
            )
            read_thread.start()

            proc.stdin.write("uci\n")
            proc.stdin.flush()
            time.sleep(0.2)
            #
            output = self.get_engine_output(proc)
            print("uci init:", output)
            # time.sleep(2)
            # output = self.get_engine_output(proc)
            # print("uci init #2:", output)

    def _read_output(self, i):
        pipe = self.engines[i].stdout
        read_queue = self.output_queue[i]
        while True:
            line = pipe.readline()
            if not line:
                # 进程关闭管道。
                break
            # print("read output thread:", i, line)
            read_queue.put(line.strip())

    def get_engine_output(self, engine, timeout=1):
        if engine.poll() is not None:
            print("引擎已退出，返回值:", engine.returncode)

            engine.terminate()  # 或 kill()
            _, stderr_data = engine.communicate()  # 读取所有剩余错误输出
            if stderr_data:
                print("最终错误信息:", stderr_data)
            return
        else:
            print("引擎运行中")

        index = self.engines.index(engine)
        read_queue = self.output_queue[index]
        print("get_engine_output:", index)

        output = []
        start_time = time.time()
        while True:
            try:
                line = read_queue.get(timeout=0.5)
                # print("queue read:", line)
                output.append(line)
                # if line.startswith("bestmove"):  # 终止标记
                #     break
            except queue.Empty:
                print("queue empty!")
                if time.time() - start_time > timeout:
                    # raise TimeoutError("等待响应超时")
                    break
                continue

        print("get_engine_output finish!")
        return output

    def get_engine(self):
        for i, lock in enumerate(self.locks):
            if lock.acquire(blocking=False):
                return self.engines[i], lock
        raise RuntimeError("无空闲引擎")

    def release_engine(self, engine, lock):
        lock.release()

    def init_app(self, app):
        pass

    def get_output_xx123(self, engine):
        def nonblocking_read(pipe, timeout=1.0):
            ready, _, _ = select.select([pipe], [], [], timeout)
            if ready:
                return pipe.readline().strip()
            return None  # 超时返回None
        output = []
        while True:
            line = nonblocking_read(engine.stdout, 1)
            if line is None:
                break
            output.append(line)
        print("\n".join(output))
        return output
